#include <float.h>
#include "common/utils.h"

namespace vehicle {
namespace tools{

//获取当前系统时间
void GetTime(std::string *date_time) {
  time_t rawtime;
  struct tm *ptminfo;
  char buf[32];

  time(&rawtime);
  ptminfo = localtime(&rawtime);
  strftime(buf, 32, "%Y-%m-%d %H:%M:%S", ptminfo);
  *date_time = buf;
}


int64_t getCurrentTime() {
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
}

bool fileExists(const std::string& filename) {
    std::ifstream file(filename.c_str());
    return file.good();
}

bool DirectoryExists(const std::string &directory_path) {
  struct stat info;
  if (stat(directory_path.c_str(), &info) != 0) {
    return false;
  }

  if (info.st_mode & S_IFDIR) {
    return true;
  }

  return false;
}


bool EnsureDirectory(const std::string &directory_path) {
  std::string path = directory_path;
  for (size_t i = 1; i < directory_path.size(); ++i) {
    if (directory_path[i] == '/') {
      // Whenever a '/' is encountered, create a temporary view from
      // the start of the path to the character right before this.
      path[i] = 0;

      if (mkdir(path.c_str(), S_IRWXU) != 0) {
        if (errno != EEXIST) {
          return false;
        }
      }
      // Revert the temporary view back to the original.
      path[i] = '/';
    }
  }

  // Make the final (full) directory.
  if (mkdir(path.c_str(), S_IRWXU) != 0) {
    if (errno != EEXIST) {
      return false;
    }
  }

  return true;
}

bool RemoveAllFiles(const std::string &directory_path) {
  DIR *directory = opendir(directory_path.c_str());
  if (directory == nullptr) {
    return false;
  }

  struct dirent *file;
  while ((file = readdir(directory)) != nullptr) {
    // skip directory_path/. and directory_path/..
    if (!strcmp(file->d_name, ".") || !strcmp(file->d_name, "..")) {
      continue;
    }
    // build the path for each file in the folder
    std::string file_path = directory_path + "/" + file->d_name;
    if (unlink(file_path.c_str()) < 0) {
      closedir(directory);
      return false;
    }
  }
  closedir(directory);
  return true;
}


std::vector<std::string> ListSubPaths(const std::string &directory_path,
                                      const unsigned char d_type) {
  std::vector<std::string> result;
  DIR *directory = opendir(directory_path.c_str());
  if (directory == nullptr) {
    return result;
  }

  struct dirent *entry;
  while ((entry = readdir(directory)) != nullptr) {
    // Skip "." and "..".
    if (entry->d_type == d_type && strcmp(entry->d_name, ".") != 0 &&
        strcmp(entry->d_name, "..") != 0) {
      result.emplace_back(entry->d_name);
    }
  }
  closedir(directory);
  return result;
}

std::string formatFloat(double value, int precision) {
    std::ostringstream stream;
    stream << std::fixed << std::setprecision(precision) << value;
    return stream.str();
}

double calDiffBetweenTwoAngle(const double& a1, const double& a2)
{
    double diff = a1 - a2;
    if (diff < 0)
        diff = a2 - a1;
    if (diff > M_PI)
        diff = 2.0 * M_PI - diff;
    return diff;
}
/**
 * @description:将当前角度转换到0～2pi 
 * @param {type} 
 * @return: 
 */
double cast_from_0_to_2PI_Angle(const double& ang)
{
    double angle = 0;
    if (ang < -2.0 * M_PI || ang > 2.0 * M_PI) {
        angle = fmod(ang, 2.0 * M_PI);
    } else
        angle = ang;

    if (angle < 0) {
        angle = 2.0 * M_PI + angle;
    }
    return angle;
}
/**
 * @description:将当前角度转换到-pi~pi 
 * @param {type} 
 * @return: 
 */
double cast_from_PI_to_PI_Angle(const double& ang)
{
    double angle = 0;
    if (ang < -2.0 * M_PI || ang > 2.0 * M_PI) {
        angle = fmod(ang, 2.0 * M_PI);
    } else
        angle = ang;

    if (angle < -M_PI) {
        angle += 2.0 * M_PI;
    } else if (angle > M_PI) {
        angle -= 2.0 * M_PI;
    }
    return angle;
}

double diffBetweenTwoAngle(const double& a1, const double& a2)
{
    double diff = a1 - a2;
    if (diff < 0)
        diff = -diff;
    if (diff > M_PI)
        diff = 2 * M_PI - diff;
    return diff;
}
}
} // namespace UtilityNS
